﻿using Force.DeepCloner;
using JavaDevToys.Rcl.Models;
using JavaDevToys.Rcl.Utils;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Scriban;
using Scriban.Runtime;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JavaDevToys.Rcl.Service.Impl
{
    public class JavaCodeGenerator : IJavaCodeGenerator
    {
        private IDirectoryPicker directoryPicker;
        private ISettingService settingService;

        public JavaCodeGenerator(IDirectoryPicker directoryPicker, ISettingService settingService)
        {
            this.directoryPicker = directoryPicker;
            this.settingService = settingService;
        }

        public List<string> GenerateModel(JavaProjectInfo javaProjectInfo, ApiInfo apiInfo)
        {
            List<string> pathList = new List<string>();

            // 生成请求类
            string requestClassPath = GenerateRequestClass(javaProjectInfo, apiInfo);
            pathList.Add(requestClassPath);

            // 生成响应类
            string responseClassPath = GenerateResponseClass(javaProjectInfo, apiInfo);
            if (!string.IsNullOrWhiteSpace(responseClassPath)) { 
                pathList.Add(responseClassPath);
            }

            //// 生成复杂类型的类
            //List<string> dtoClassPath = GenerateComplexClasses(javaProjectInfo, apiInfo);
            //pathList.AddRange(dtoClassPath);

            return pathList;
        }

        public void GenerateDtoModel(JavaProjectInfo javaProjectInfo, ApiInfo _apiInfo, out List<string> newFileList, out Dictionary<string, string> fixCodeDict)
        {
            newFileList = new List<string>();
            fixCodeDict = new Dictionary<string, string>();
            foreach (var item in _apiInfo.DtoParameters)
            {
                //是否已经生成了dto
                if (directoryPicker.SearchFile(javaProjectInfo.FullPath, $"{item.Key}.java", out string fullPath))
                {
                    //读取已经生成的dto
                    string templateContent = File.ReadAllText(fullPath);
                    var dtoParams = item.Value.DeepClone();
                    List<ParameterInfo> removeParams = new List<ParameterInfo>();
                    //移除已经生成的属性
                    foreach (var parameterInfo in dtoParams)
                    {
                        if (templateContent.Contains($" {parameterInfo.ParameterName};"))
                        {
                            removeParams.Add(parameterInfo);
                        }
                    }
                    foreach (var parameter in removeParams)
                    {
                        dtoParams.Remove(parameter);
                    }
                    if (dtoParams.Count > 0)
                    {
                        string newCode = GenerateDtoCode(dtoParams);
                        fixCodeDict.Add(fullPath, newCode);
                    }
                }
                else
                {
                    var filePathList = GenerateComplexClasses(javaProjectInfo, item.Key, item.Value);
                    newFileList.AddRange(filePathList);
                }
            }
        }

        private string GenerateDtoCode(List<ParameterInfo> parameterInfos)
        {
            var context = new JavaTempData()
            {
                parameters = parameterInfos.Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.DataType,
                    description = s.Description,
                    parameter_name = s.ParameterName,
                    required = s.IsRequired,
                }).ToList(),
            };

            string result = CreateCodeWithTemp("TemplateClass.Parameter.scriban", context);
            return result;
        }

        private string GenerateRequestClass(JavaProjectInfo javaProjectInfo, ApiInfo apiInfo)
        {
            string fileFullName = Path.Combine(
                javaProjectInfo.RequestClassPath,
                $"{JavaCodeHelper.ToUpperFirst(apiInfo.MethodName)}Request.java"
            );

            string packageName = ExtractPackageName(fileFullName);

            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = apiInfo.MethodName,
                parameters = apiInfo.RequestParameters.Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.DataType,
                    description = s.Description,
                    parameter_name = s.ParameterName,
                    required = s.IsRequired,
                }).ToList(),
                base_class = apiInfo.IsPaginated ? "BasePageRequest" : "BaseRequest",
            };

            string result = CreateCodeWithTemp("TemplateRequestClass.scriban", context);
            WriteJavaFile(fileFullName, result);
            return fileFullName;
        }

        private string GenerateResponseClass(JavaProjectInfo javaProjectInfo, ApiInfo apiInfo)
        {
            if(apiInfo.ResponseParameters.Count == 0)
            {
                return string.Empty;
            }
            string fileFullName = Path.Combine(
                javaProjectInfo.ResponseClassPath,
                $"{JavaCodeHelper.ToUpperFirst(apiInfo.MethodName)}Response.java"
            );

            string packageName = ExtractPackageName(fileFullName);

            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = apiInfo.MethodName,
                parameters = apiInfo.ResponseParameters.Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.DataType,
                    description = s.Description,
                    parameter_name = s.ParameterName,
                    required = s.IsRequired,
                }).ToList(),
            };

            string result = CreateCodeWithTemp("TemplateResponseClass.scriban", context);
            WriteJavaFile(fileFullName, result);
            return fileFullName;
        }

        private List<string> GenerateComplexClasses(JavaProjectInfo javaProjectInfo, string className, List<ParameterInfo> parameterInfos)
        {
            List<string> classPaths = new List<string>();
            string fileFullName = Path.Combine(
                    javaProjectInfo.RequestClassPath,
                    $"{className}.java"
                );
            string packageName = ExtractPackageName(fileFullName);
            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = className,
                parameters = parameterInfos.Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.DataType,
                    description = s.Description,
                    parameter_name = s.ParameterName,
                    required = s.IsRequired,
                }).ToList(),
            };

            string result = CreateCodeWithTemp("TemplateDtoClass.scriban", context);
            WriteJavaFile(fileFullName, result);
            classPaths.Add(fileFullName);
            return classPaths;
        }

        private string ExtractPackageName(string fileFullName)
        {
            var fullDirName = Path.GetDirectoryName(fileFullName);
            return fullDirName.Substring(fullDirName.LastIndexOf(Path.DirectorySeparatorChar+"com"+ Path.DirectorySeparatorChar)+1)
                .Replace('/', '.')
                .Replace('\\', '.');
        }

        private List<string> GetImports(IEnumerable<ParameterInfo> parameters)
        {
            var imports = new HashSet<string>();
            if (parameters.Any(p => p.DataType.ToLower().Contains("date"))) imports.Add("java.util.Date");
            if (parameters.Any(p => p.DataType.ToLower().Contains("list"))) imports.Add("java.util.List");
            if (parameters.Any(p => p.DataType.ToLower().Contains("bigdecimal"))) imports.Add("java.math.BigDecimal");
            if (parameters.Any(p => p.DataType.ToLower().Contains("dto"))) imports.Add("javax.validation.Valid");
            return imports.ToList();
        }

        public List<string> GenerateService(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            List<string> fileFullNameList = new List<string>();
            var classList = javaServiceInfos.Select(s => s.ClassName).Distinct().ToList();

            foreach (var item in classList)
            {
                var javaServiceList = javaServiceInfos.Where(w => w.ClassName == item).ToList();
                string className = $"{item.Substring(0, 1).ToUpper() + item.Substring(1)}Controller";
                string fileFullName = Path.Combine(directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "controller"), $"{className}.java");
                var fullDirName = Path.GetDirectoryName(fileFullName);
                // 准备数据
                var modelData = new
                {
                    package_name = directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "controller").Substring(fullDirName.LastIndexOf(Path.DirectorySeparatorChar + "com" + Path.DirectorySeparatorChar) + 1).Replace('/', '.').Replace('\\', '.'),
                    class_name = item,
                    model_name = javaServiceList.FirstOrDefault()?.ModelName,
                    date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    methods = javaServiceList.Select(m => new
                    {
                        code = m.Code,
                        name = m.Name,
                        mothedName = m.MothedName
                    }).ToList()
                };

                // Controller
                GenerateFile("TempController.scriban", modelData, directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "controller"), $"{item}Controller.java", fileFullNameList);

                // Work 接口
                GenerateFile("TemplateWorkService.scriban", modelData, directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "work"), $"{item}WorkService.java", fileFullNameList);

                // Work 实现类
                GenerateFile("TemplateWorkServiceImpl.scriban", modelData, Path.Combine(directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "work"), "impl"), $"{item}WorkServiceImpl.java", fileFullNameList);
            }

            return fileFullNameList;
        }


        private void GenerateFile(string templateName, object data, string outputDir, string fileName, List<string> fileFullNameList)
        {
            var templatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JavaTemp", templateName);
            var templateContent = File.ReadAllText(templatePath);
            var template = Template.Parse(templateContent);
            // 创建 TemplateContext 并启用内置函数
            var context = new TemplateContext();
            var scriptObject = new ScriptObject();
            scriptObject.Import(data); // 将数据导入到模板
            context.PushGlobal(scriptObject);

            // 启用内置的 "replace" 函数
            scriptObject.Import(typeof(JavaCodeHelper));

            var result = template.Render(context);

            var fileFullName = Path.Combine(outputDir, fileName);
            Directory.CreateDirectory(Path.GetDirectoryName(fileFullName));
            File.WriteAllText(fileFullName, result);

            fileFullNameList.Add(fileFullName);
        }
        /// <summary>
        /// 根据模板生成代码
        /// </summary>
        private string CreateCodeWithTemp(string templateName, object data)
        {
            var templatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JavaTemp", templateName);
            var templateContent = File.ReadAllText(templatePath);
            var template = Template.Parse(templateContent);
            // 创建 TemplateContext 并启用内置函数
            var context = new TemplateContext();
            var scriptObject = new ScriptObject();
            scriptObject.Import(data); // 将数据导入到模板
            context.PushGlobal(scriptObject);

            // 启用内置函数
            scriptObject.Import(typeof(JavaCodeHelper));

            var result = template.Render(context);
            return result;
        }


        public string GenerateParameter(List<ParameterInfo> parameterInfos)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var param in parameterInfos)
            {
                // 添加@ApiModelProperty注解
                sb.AppendLine($"\t@ApiModelProperty(value=\"{param.Description}\")");

                // 根据是否必填及数据类型添加验证注解
                var validationAnnotation = GetValidationAnnotation(param);
                if (!string.IsNullOrEmpty(validationAnnotation))
                {
                    sb.AppendLine($"\t{validationAnnotation}");
                }

                sb.AppendLine($"\tprivate {MapDataType(param.DataType, param.ParameterName)} {param.ParameterName};");
                sb.AppendLine();
            }
            return sb.ToString();
        }

        private void WriteJavaFile(string fileName, string content)
        {
            string filePath = Path.Combine(fileName);
            if (!Directory.Exists(Path.GetDirectoryName(fileName)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(fileName));
            }
            File.WriteAllText(filePath, content, new UTF8Encoding(false));
            Console.WriteLine($"生成文件: {filePath}");
        }



        private string GetValidationAnnotation(ParameterInfo param)
        {
            if (!param.IsRequired)
                return string.Empty;

            // 根据数据类型选择适当的验证注解
            string annotation = string.Empty;
            switch (param.DataType.ToLower())
            {
                case "string":
                    annotation = "@NotBlank(message=\"" + param.Description + "不能为空\")";
                    break;
                case "integer":
                case "long":
                case "double":
                case "float":
                case "boolean":
                    annotation = "@NotNull(message=\"" + param.Description + "不能为空\")";
                    break;
                default:
                    if (IsListType(param.DataType))
                    {
                        annotation = "@NotEmpty(message=\"" + param.Description + "不能为空\")";
                    }
                    else
                    {
                        annotation = "@NotNull(message=\"" + param.Description + "不能为空\")";
                    }
                    break;
            }

            return annotation;
        }

        private List<string> GetCSharpValidationAnnotation(ParameterInfo param)
        {
            if (!param.IsRequired)
                return new List<string>();

            // 根据数据类型选择适当的验证注解
            List<string> annotation = new List<string>();
            switch (param.DataType.ToLower())
            {
                case "string":
                case "integer":
                case "long":
                case "double":
                case "float":
                case "boolean":
                    annotation.Add($"[Required(ErrorMessage = \"{param.Description}不能为空\")]");
                    break;
                default:
                    if (IsListType(param.DataType))
                    {
                        annotation.Add($"[Required(ErrorMessage = \"{param.Description}不能为空\")]");
                        annotation.Add($"[MinLength(1, ErrorMessage = \"{param.Description}不能为空\")]");
                    }
                    else
                    {
                        annotation.Add($"[Required(ErrorMessage = \"{param.Description}不能为空\")]");
                    }
                    break;
            }

            return annotation;
        }

        private string MapDataType(string dataType, string parameterName)
        {
            // 映射数据类型，可根据需要扩展
            switch (dataType.ToLower())
            {
                case "string":
                    return "String";
                case "integer":
                    return "Integer";
                case "long":
                    return "Long";
                case "double":
                    return "Double";
                case "float":
                    return "Float";
                case "datetime":
                    return "Date";
                case "time":
                    return "Date";
                case "boolean":
                    return "Boolean";
                case "list<Class>":
                    return $"List<{parameterName.Replace("List", "DTO")}>";
                default:
                    // 如果遇到未知类型，直接返回原始类型
                    return dataType;
            }
        }

        private bool IsListType(string dataType)
        {
            return dataType.Trim().StartsWith("List<", StringComparison.OrdinalIgnoreCase);
        }


        public List<string> GenerateMapper(JavaProjectInfo javaProjectInfo, JavaMapperInfo javaMapperInfo)
        {
            return GenerateJavaFiles(javaProjectInfo, javaMapperInfo);
        }

        private List<string> GenerateJavaFiles(JavaProjectInfo javaProjectInfo, JavaMapperInfo javaMapperInfo)
        {
            List<string> result = new List<string>();
            string queryColumns = @"
                SELECT 
                    c.COLUMN_NAME, 
                    c.DATA_TYPE, 
                    c.IS_NULLABLE, 
                    c.COLUMN_DEFAULT,
                    ep.value AS COLUMN_COMMENT,
                    CASE WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1 ELSE 0 END AS IS_PRIMARY_KEY,
                    c.NUMERIC_PRECISION,
                    c.NUMERIC_SCALE
                FROM INFORMATION_SCHEMA.COLUMNS c
                LEFT JOIN sys.columns sc 
                    ON sc.object_id = OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME))
                    AND sc.name = c.COLUMN_NAME
                LEFT JOIN sys.extended_properties ep 
                    ON ep.major_id = sc.object_id 
                    AND ep.minor_id = sc.column_id 
                    AND ep.name = 'MS_Description'
                LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
                    ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
                    AND kcu.TABLE_NAME = c.TABLE_NAME
                    AND kcu.COLUMN_NAME = c.COLUMN_NAME
                    AND kcu.CONSTRAINT_NAME IN (
                        SELECT CONSTRAINT_NAME 
                        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
                        WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
                          AND TABLE_SCHEMA = c.TABLE_SCHEMA
                          AND TABLE_NAME = c.TABLE_NAME
                    )
                LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
                    ON tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
                    AND tc.TABLE_NAME = kcu.TABLE_NAME
                    AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
                    AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
                WHERE c.TABLE_SCHEMA = @TableSchema AND c.TABLE_NAME = @TableName
                ORDER BY c.ORDINAL_POSITION";
            string connectionString = SqlServerHelp.BuildConnectionString(javaProjectInfo.sqlserverInfo.Server, javaProjectInfo.sqlserverInfo.Database, javaProjectInfo.sqlserverInfo.UserName, javaProjectInfo.sqlserverInfo.Pwd);
            // 收集字段信息
            var columns = new List<ColumnInfo>();
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();
                SqlCommand cmdColumns = new SqlCommand(queryColumns, connection);
                cmdColumns.Parameters.AddWithValue("@TableSchema", javaProjectInfo.sqlserverInfo.Schemas);
                cmdColumns.Parameters.AddWithValue("@TableName", javaMapperInfo.TableName);
                SqlDataReader readerColumns = cmdColumns.ExecuteReader();

                while (readerColumns.Read())
                {
                    string columnName = readerColumns["COLUMN_NAME"].ToString();
                    string dataType = readerColumns["DATA_TYPE"].ToString();
                    string columnComment = readerColumns["COLUMN_COMMENT"] != DBNull.Value ? readerColumns["COLUMN_COMMENT"].ToString() : "";
                    bool isPrimaryKey = Convert.ToInt32(readerColumns["IS_PRIMARY_KEY"]) == 1;
                    int? precision = readerColumns["NUMERIC_PRECISION"] != DBNull.Value ? (int?)Convert.ToInt32(readerColumns["NUMERIC_PRECISION"]) : null;
                    int? scale = readerColumns["NUMERIC_SCALE"] != DBNull.Value ? (int?)Convert.ToInt32(readerColumns["NUMERIC_SCALE"]) : null;

                    columns.Add(new ColumnInfo
                    {
                        ColumnName = columnName,
                        DataType = dataType,
                        ColumnComment = columnComment,
                        IsPrimaryKey = isPrimaryKey,
                        Precision = precision,
                        Scale = scale
                    });
                }

                readerColumns.Close();
            }


            // 生成Java文件
            string daminPath = GenerateDomainClass(javaProjectInfo, javaMapperInfo.TableName, columns);
            string mapperPath = GenerateMapperInterface(javaProjectInfo, javaMapperInfo.TableName);
            string mapperXmlPath = GenerateMapperXml(javaProjectInfo, javaMapperInfo.TableName, columns);
            string daoServerPath = GenerateDaoServer(javaProjectInfo, javaMapperInfo.TableName, columns);
            string daoServerImplPath = GenerateDaoServerImpl(javaProjectInfo, javaMapperInfo.TableName, columns);
            result.Add(daminPath);
            result.Add(mapperPath);
            result.Add(mapperXmlPath);
            result.Add(daoServerPath);
            result.Add(daoServerImplPath);
            return result;
        }

        private string GenerateDaoServerImpl(JavaProjectInfo javaProjectInfo, string tableName, List<ColumnInfo> columns)
        {
            string domainClassName = JavaCodeHelper.ToPascalCase(tableName);
            string fileFullName = Path.Combine(javaProjectInfo.DaoImplPath, $"{domainClassName}ServiceImpl.java");

            string packageName = ExtractPackageName(fileFullName);

            var primaryKey = columns.FirstOrDefault(f => f.IsPrimaryKey)?.JavaName;

            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = domainClassName,
                primary_key_name = primaryKey,
            };
            string result = CreateCodeWithTemp("TemplateDaoServiceImpl.scriban", context);

            WriteJavaFile(fileFullName, result);
            return fileFullName;
        }

        private string GenerateDaoServer(JavaProjectInfo javaProjectInfo, string tableName, List<ColumnInfo> columns)
        {
            string domainClassName = JavaCodeHelper.ToPascalCase(tableName);
            string fileFullName = Path.Combine(javaProjectInfo.DaoPath, $"{domainClassName}Service.java");

            string packageName = ExtractPackageName(fileFullName);

            var primaryKey = columns.FirstOrDefault(f => f.IsPrimaryKey)?.JavaName;
            if (primaryKey == null)
            {
                throw new ArgumentException("No primary key found in the columns.");
            }

            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = domainClassName,
                primary_key_name = primaryKey,
            };
            string result = CreateCodeWithTemp("TemplateDaoService.scriban", context);

            WriteJavaFile(fileFullName, result);
            return fileFullName;
        }

        // 生成Domain类
        private string GenerateDomainClass(JavaProjectInfo javaProjectInfo, string tableName, List<ColumnInfo> columns)
        {
            List<string> baseColumns = new List<string>()
            {
                "createdOrgLocationId","createdUserId","createdAt","modifiedOrgLocationId","modifiedUserId","modifiedAt"
            };
            string domainClassName = JavaCodeHelper.ToPascalCase(tableName);


            string fileFullName = Path.Combine(
                javaProjectInfo.DomainPath,
                $"{domainClassName}Domain.java"
            );

            string packageName = ExtractPackageName(fileFullName);

            var context = new JavaTempData()
            {
                model_name = tableName,
                package_name = packageName,
                class_name = domainClassName,
                parameters = columns.Where(w => !baseColumns.Contains(w.JavaName)).Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.JavaType,
                    description = s.ColumnComment,
                    parameter_name = s.JavaName,
                    is_primary_key = s.IsPrimaryKey,
                    column_name = s.ColumnName,
                }).ToList(),
            };
            string result = CreateCodeWithTemp("TemplateDomain.scriban", context);
            WriteJavaFile(fileFullName, result);
            return fileFullName;
        }

        // 生成Mapper接口
        private string GenerateMapperInterface(JavaProjectInfo javaProjectInfo, string tableName)
        {
            string domainClassName = JavaCodeHelper.ToPascalCase(tableName);

            string fileFullName = Path.Combine(
                javaProjectInfo.MapperPath,
                $"{JavaCodeHelper.ToUpperFirst(domainClassName)}Mapper.java"
            );

            string packageName = ExtractPackageName(fileFullName);

            var context = new JavaTempData()
            {
                package_name = packageName,
                class_name = domainClassName,
            };

            string resultCode = CreateCodeWithTemp("TemplateMapper.scriban", context);

            // 写入文件
            WriteJavaFile(fileFullName, resultCode);
            return fileFullName;
        }

        public List<string> GenerateEnum(JavaProjectInfo javaProjectInfo, IEnumerable<DictCodeSystem> selectedDictCodeSystems, IEnumerable<DictDataSets> dictDataSets, string selectedFolder = null)
        {
            List<string> result = new List<string>();
            if (string.IsNullOrWhiteSpace(selectedFolder))
            {
                selectedFolder = directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "enums");
            }
            foreach (var item in selectedDictCodeSystems)
            {
                string domainClassName = JavaCodeHelper.ToPascalCase(item.codeSystemNo);
                string fileFullName = Path.Combine(selectedFolder, $"{domainClassName}Enum.java");
                var fullDirName = Path.GetDirectoryName(fileFullName);
                string packageName = fullDirName.Substring(fullDirName.LastIndexOf(Path.DirectorySeparatorChar + "com" + Path.DirectorySeparatorChar) + 1).Replace('/', '.').Replace('\\', '.');

                var context = new JavaTempData()
                {
                    model_name = item.codeSystemName,
                    package_name = packageName,
                    class_name = domainClassName,
                    parameters = dictDataSets.Where(w => w.codeSystemId == item.codeSystemId).Select(s => new JavaTempData_Parameter()
                    {
                        data_type = s.dataValueNo,
                        description = s.dataValueCnName,
                        parameter_name = s.dataValueCnName,
                    }).ToList(),
                };

                string resultCode = CreateCodeWithTemp("TemplateEnum.scriban", context);

                WriteJavaFile(fileFullName, resultCode);
                result.Add(fileFullName);
            }

            return result;
        }

        public string GenerateEnumCode(IEnumerable<DictDataSets> dictDataSets)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var dataSet in dictDataSets)
            {
                sb.AppendLine($"\t{JavaCodeHelper.GetPinyinInitials(dataSet.dataValueCnName)}(\"{dataSet.dataValueNo}\",\"{dataSet.dataValueCnName}\"),");
            }
            return sb.ToString();
        }

        // 生成Mapper XML文件
        private string GenerateMapperXml(JavaProjectInfo javaProjectInfo, string tableName, List<ColumnInfo> columns)
        {
            string domainClassName = JavaCodeHelper.ToPascalCase(tableName);
            string mapperFullName = Path.Combine(directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "mapper"), $"{domainClassName}Mapper.java");
            string domainFullName = Path.Combine(directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "domain"), $"{domainClassName}Domain.java");
            string fileFullName = Path.Combine(directoryPicker.SearchDirectory(javaProjectInfo.FullPath, "mapper", "resources"), $"{domainClassName}Mapper.xml");
            var fullDirName = Path.GetDirectoryName(fileFullName);
            var mapperFullDirName = Path.GetDirectoryName(mapperFullName);
            var domainFullDirName = Path.GetDirectoryName(domainFullName);
            string mapperPackageName = mapperFullDirName.Substring(mapperFullDirName.LastIndexOf(Path.DirectorySeparatorChar + "com" + Path.DirectorySeparatorChar) + 1).Replace('/', '.').Replace('\\', '.');
            string domainPackageName = domainFullDirName.Substring(domainFullDirName.LastIndexOf(Path.DirectorySeparatorChar + "com" + Path.DirectorySeparatorChar) + 1).Replace('/', '.').Replace('\\', '.');
            string mapperInterfaceName = $"{domainClassName}Mapper";
            var xmlContent = new StringBuilder();

            xmlContent.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
            xmlContent.AppendLine("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">");
            xmlContent.AppendLine($"<mapper namespace=\"{mapperPackageName}.{mapperInterfaceName}\">");
            xmlContent.AppendLine("");

            // ResultMap
            xmlContent.AppendLine($"    <resultMap id=\"{domainClassName}ResultMap\" type=\"{domainPackageName}.{domainClassName}Domain\">");
            foreach (var column in columns)
            {
                if (column.IsPrimaryKey)
                {
                    xmlContent.AppendLine($"        <id column=\"{column.ColumnName}\" jdbcType=\"{ToJavaJdbcType(column.DataType)}\" property=\"{column.JavaName}\" />");
                }
                else
                {
                    xmlContent.AppendLine($"        <result column=\"{column.ColumnName}\" jdbcType=\"{ToJavaJdbcType(column.DataType)}\" property=\"{column.JavaName}\" />");
                }
            }
            xmlContent.AppendLine("    </resultMap>");
            xmlContent.AppendLine("");


            xmlContent.AppendLine("");



            xmlContent.AppendLine("</mapper>");

            // 写入文件
            WriteJavaFile(fileFullName, xmlContent.ToString());
            return fileFullName;
        }

        private string ToJavaJdbcType(string datatype)
        {
            switch (datatype)
            {
                case "datetime":
                    return "TIMESTAMP";
                case "int":
                    return "INTEGER";
                default:
                    return datatype.ToUpper();
            }
        }

        private Dictionary<string, string> GenerateService(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos, string tempName, Func<JavaProjectInfo, string> getFilePath)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, tempName, getFilePath.Invoke(javaProjectInfo));
        }
        private Dictionary<string, string> GenerateService(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos, string tempName, string filePath)
        {
            Dictionary<string, string> codeList = new Dictionary<string, string>();
            var classList = javaServiceInfos.Select(s => s.ClassName).Distinct().ToList();

            foreach (var item in classList)
            {
                var javaServiceList = javaServiceInfos.Where(w => w.ClassName == item).ToList();
                string className = string.Empty;
                if (tempName.Contains("Controller"))
                {
                    className = $"{item.Substring(0, 1).ToUpper() + item.Substring(1)}Controller";
                }
                else
                if (tempName.Contains("WorkServiceImpl"))
                {
                    className = $"{item.Substring(0, 1).ToUpper() + item.Substring(1)}WorkServiceImpl";
                }
                else
                    if (tempName.Contains("WorkService"))
                {
                    className = $"{item.Substring(0, 1).ToUpper() + item.Substring(1)}WorkService";
                }
                string fileFullName = Path.Combine(filePath, $"{className}.java");
                var fullDirName = filePath;
                // 准备数据
                var modelData = new JavaTempData()
                {
                    package_name = fullDirName.Substring(fullDirName.LastIndexOf(Path.DirectorySeparatorChar + "com" + Path.DirectorySeparatorChar) + 1).Replace('/', '.').Replace('\\', '.'),
                    class_name = item,
                    model_name = javaServiceList.FirstOrDefault()?.ModelName,
                    date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    methods = javaServiceList.Select(m => new JavaTempData_Method()
                    {
                        code = m.Code,
                        name = m.Name,
                        mothedName = m.MothedName
                    }).ToList()
                };
                var javaCode = CreateCodeWithTemp(tempName, modelData);
                codeList.Add(className, javaCode);
            }

            return codeList;
        }

        public Dictionary<string, string> GenerateController(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateController.scriban", p => p.ControllerPath);
        }

        public Dictionary<string, string> GenerateWork(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateWorkService.scriban", p => p.WorkPath);
        }

        public Dictionary<string, string> GenerateWorkImpl(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateWorkServiceImpl.scriban", p => p.WorkImplPath);
        }

        public bool CheckFiledExists(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos, out string filePath)
        {
            throw new NotImplementedException();
        }

        public Dictionary<string, string> GenerateControllerMethod(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateController.Method.scriban", p => p.ControllerPath);
        }

        public Dictionary<string, string> GenerateWorkMethod(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateWorkService.Method.scriban", p => p.WorkPath);
        }

        public Dictionary<string, string> GenerateWorkImplMethod(JavaProjectInfo javaProjectInfo, List<JavaServiceInfo> javaServiceInfos)
        {
            return GenerateService(javaProjectInfo, javaServiceInfos, "TemplateWorkServiceImpl.Method.scriban", p => p.WorkImplPath);
        }

        public string GenerateCSharpParameter(List<ParameterInfo> parameterInfos)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var param in parameterInfos)
            {
                // 添加@ApiModelProperty注解
                sb.AppendLine($"\t/// <summary>");
                sb.AppendLine($"\t/// {param.Description}");
                sb.AppendLine($"\t/// <summary>");

                // 根据是否必填及数据类型添加验证注解
                var validationAnnotation = GetCSharpValidationAnnotation(param);
                foreach (var annotation in validationAnnotation)
                {
                    sb.AppendLine($"\t{annotation}");
                }

                sb.AppendLine($"\tpublic {param.DataType} {param.ParameterName} {{ get; set; }}");
                sb.AppendLine();
            }
            return sb.ToString();
        }
    }
}
